# -*- coding: utf-8 -*-
"""
派生密钥管理视图
"""

import base64
from datetime import datetime
from django.shortcuts import render
from django.http import HttpRequest, HttpResponse
from django.views.generic import View
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from rest_framework.request import Request
from apps.generate_secret.models import AppSecret
from apps.keys_management.models import RootKey
from utils.common_tools import get_client_ip, validate_signature, validate_signature_token
from utils.crypto_tools import command_derive_key, command_encrypt
from utils.jsonResponse import SuccessResponse, ErrorResponse, DetailResponse
from apps.derive_keys_management.models import DeriveKey, DeriveKeyAuditLog
# from apps.generate_secret.tools import validate_signature_token
from django.db.models import Q
import logging
from django.core.cache import cache
import json
import traceback
from datetime import datetime, timedelta

from utils.sm2_crypto_fixed import auto_fix_and_retry, create_sm2_public_key, load_certificate_from_data

log = logging.getLogger('log')


class DeriveKeyViews(APIView):
    """派生密钥管理API"""

    def post(self, request: Request):
        """
        生成派生密钥或查询密钥
        根据URL路径判断操作类型
        """
        # 获取当前URL路径
        current_path = request.path
        
        if 'generateDerive' in current_path:
            return self._generate_derive_key(request)
        elif 'search' in current_path:
            return self._search_key(request)
        else:
            log.warning(f"无效的URL路径: {current_path}")
            return ErrorResponse(data="无效的URL路径")

    def add_secrets(self, cert, key) -> str:
        x_coord, y_coord = load_certificate_from_data(cert)
        sm2_public_key = create_sm2_public_key(x_coord, y_coord)
        # key = bytes(keyo
        key = base64.b64decode(key)
        # key = bytes(b"000102030405060708090A0B0C0D0E0F")
        encrypt_bytes, method = auto_fix_and_retry(key, x_coord, y_coord)
        print(type(encrypt_bytes), encrypt_bytes)
        return encrypt_bytes


    def _generate_derive_key(self, request: Request):
        """
        生成派生密钥
        POST /keys/generateDerive
        请求体: {
            "algorithm": "AES-256",
            "purpose": "encryption",
            "description": "设备数据加密密钥",
            "expiry_days": 1,
            "derive_id": "device_001",
            "datetime": "20250102153211000",
            "root_key_id": "key_1234567890abcdef",
            "user_cert": "-----BEGIN CERTIFICATE-----MIIBIjANBgkqh...-----END CERTIFICATE-----"
        }
        头信息: {
            "APP-ID": "your_app_id",
            "TOKEN": "your_signature_token"
        }
        参数: {
            "senderNonce": "sender_nonce_value",
            "recipNonce": "recip_nonce_value", 
            "messageTime": "20250101000000000"
        }
        """
        client_ip = get_client_ip(request)
        request_id = f"req_{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}"
        headers = dict(request.headers)
        body = json.loads(request.body)
        env = body.get('env', 'prod') # dev, prod
        
        log.info(f"[{request_id}] 开始处理生成派生密钥请求 - IP: {client_ip}, 路径: {request.path}")
        log.info(f"[{request_id}] ====请求头信息: {headers}")
        log.info(f"[{request_id}] ====请求body: {body}")

        now = datetime.now()
        datetime_str = now.strftime('%Y%m%d%H%M%S') + f"{int(now.microsecond/1000):03d}"

        
        # 签名校验
        is_valid, error_msg = validate_signature(headers, body)
        if not is_valid:
            log.warning(f"[{request_id}] 签名校验失败: {error_msg}")
            return ErrorResponse(data=f"签名校验失败: {error_msg}")
        
        log.info(f"[{request_id}] 签名校验通过，开始处理业务逻辑")
        
        try:
            # 记录请求体
            request_body = request.body.decode('utf-8') if request.body else '{}'
            log.info(f"[{request_id}] 请求体: {request_body}")
            
            data = json.loads(request.body) if request.body else {}
            algorithm = data.get('algorithm', '')
            purpose = data.get('purpose', '')
            description = data.get('description', '')
            expiry_days = data.get('expiry_days', 1)
            derive_id = data.get('derive_id')
            datetime_str = data.get('datetime', datetime_str)
            root_key_id = data.get('root_key_id')
            user_cert = data.get('user_cert')
            
            log.info(f"[{request_id}] 解析参数 - algorithm: {algorithm}, purpose: {purpose}, derive_id: {derive_id}, root_key_id: {root_key_id}")

            # 参数验证
            if not algorithm:
                log.warning(f"[{request_id}] 参数验证失败: algorithm参数不能为空")
                return ErrorResponse(data="algorithm参数不能为空")
            if algorithm not in ['AES-128', 'AES-192', 'AES-256', 'DES', '3DES']:
                log.warning(f"[{request_id}] 参数验证失败: algorithm参数必须是AES-128/AES-192/AES-256/DES/3DES，当前值: {algorithm}")
                return ErrorResponse(data="algorithm参数必须是AES-128/AES-192/AES-256/DES/3DES")
            if not derive_id:
                log.warning(f"[{request_id}] 参数验证失败: derive_id参数不能为空")
                return ErrorResponse(data="derive_id参数不能为空")
            if not datetime_str:
                log.warning(f"[{request_id}] 参数验证失败: datetime参数不能为空")
                return ErrorResponse(data="datetime参数不能为空")
            if not root_key_id:
                log.warning(f"[{request_id}] 参数验证失败: root_key_id参数不能为空")
                return ErrorResponse(data="root_key_id参数不能为空")
            if not user_cert:
                log.warning(f"[{request_id}] 参数验证失败: user_cert参数不能为空")
                return ErrorResponse(data="user_cert参数不能为空")

            log.info(f"[{request_id}] 参数验证通过，开始生成派生密钥")

            # 生成派生密钥
            derive_id = derive_id.strip()
            root_key = RootKey.objects.filter(
                key_id=root_key_id,
                is_delete=False,
                status='active'
            ).first().key # 应该是base64编码的密钥

            current_date = datetime.now().strftime("%Y%m%d")
            derive_id_with_date = f"{derive_id}{current_date}"
            encoded_derive_id = base64.b64encode(derive_id_with_date.encode('utf-8')).decode('utf-8')
            
            # 用户公钥加密
            if env == 'dev':
                derive_key = self.add_secrets(user_cert, root_key) 
                derive_key = base64.b64encode(derive_key).decode("ascii")
            else:
                status, derive_key = command_derive_key(encoded_derive_id, root_key)
                log.info(f"[{request_id}] 命令行派生密钥结果: {derive_key}")
                if status != 0:
                    return ErrorResponse(code=-1, msg="派生密钥生成失败，请检查日志")

            key_id = DeriveKey.generate_key_id()
            # derive_key = DeriveKey.generate_derive_key(algorithm)
            version = DeriveKey.generate_version()
            
            # 计算过期时间
            expires_at = datetime.now() + timedelta(days=expiry_days)

            log.info(f"[{request_id}] 生成密钥信息 - key_id: {key_id}, algorithm: {algorithm}, expires_at: {expires_at}")
            app_id = headers.get('Appid')
            app_secret_obj = AppSecret.objects.filter(app_id=app_id, is_delete=False, status=True).first()

            # 创建派生密钥记录
            derive_key_obj = DeriveKey.objects.create(
                key_id=key_id,
                app_id = app_secret_obj,  # 从头信息获取app_id
                algorithm=algorithm,
                purpose=purpose,
                description=description,
                key=derive_key,
                expiry_days=expiry_days,
                derive_id=derive_id,
                root_key_id=root_key_id,
                user_cert=user_cert,
                version=version,
                expires_at=expires_at
            )

            # 记录审计日志
            DeriveKeyAuditLog.objects.create(
                key_id=key_id,
                operation='create',
                operator='system',
                ip_address=client_ip,
                user_agent='',
                details=f"生成派生密钥 - 算法: {algorithm}, 用途: {purpose}, 分散因子: {derive_id}, 根密钥: {root_key_id}",
                expired_at=expires_at
            )

            if env == 'dev':
                derive_key_scerte = derive_key
            # derive_key_scerte = self.add_secrets(user_cert, derive_key) 
            # derive_key_scerte = base64.b64encode(derive_key_scerte).decode("ascii")  # 转为Base64文本
            else:
                status, derive_key_scerte = command_encrypt(user_cert, derive_key)  # 执行加密命令
                if status != 0:
                    return ErrorResponse(code=status, data=None, msg=f"派生密钥加密失败: {derive_key_scerte}")


            result = {
                "algorithm": algorithm,
                "purpose": purpose,
                "description": description,
                "key_id": key_id,
                "key": derive_key_scerte,
                "expiry_days": expiry_days,
                "version": version
            }

            log.info(f"[{request_id}] 派生密钥生成成功 - key_id: {key_id}, algorithm: {algorithm}")

            return DetailResponse(data=result, msg="派生密钥生成成功")

        except json.JSONDecodeError as e:
            log.error(f"[{request_id}] JSON解析失败: {str(e)}, 请求体: {request_body}")
            return ErrorResponse(data="请求体格式错误，请使用JSON格式")
        except Exception as e:
            log.error(f"[{request_id}] 生成派生密钥失败: {str(e)}")
            log.error(f"[{request_id}] 异常堆栈: {traceback.format_exc()}")
            return ErrorResponse(data=f"生成派生密钥失败: {str(e)}")

    def _search_key(self, request: Request):
        """
        查询密钥
        POST /keys/search
        请求体: {
            "key_id": "key_1234567890abcdef",
            "user_cert": "-----BEGIN CERTIFICATE-----MIIBIjANBgkqh...-----END CERTIFICATE-----"
        }
        头信息: {
            "APP-ID": "your_app_id",
            "TOKEN": "your_signature_token"
        }
        参数: {
            "senderNonce": "sender_nonce_value",
            "recipNonce": "recip_nonce_value", 
            "messageTime": "20250101000000000"
        }
        """
        client_ip = get_client_ip(request)
        request_id = f"req_{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}"
        headers = dict(request.headers)
        body = json.loads(request.body)
        env = body.get('env', 'prod') # dev, prod 
        
        log.info(f"[{request_id}] 开始处理查询密钥请求 - IP: {client_ip}, 路径: {request.path}")
        log.info(f"[{request_id}] 请求头信息: {dict(request.headers)}")
        
        # 签名校验
        # is_valid, error_msg = self._validate_signature(request)
        is_valid, error_msg = validate_signature(headers, body)
        if not is_valid:
            log.warning(f"[{request_id}] 签名校验失败: {error_msg}")
            return ErrorResponse(data=f"签名校验失败: {error_msg}")
        
        log.info(f"[{request_id}] 签名校验通过，开始处理业务逻辑")
        
        try:
            # 记录请求体
            request_body = request.body.decode('utf-8') if request.body else '{}'
            log.info(f"[{request_id}] 请求体: {request_body}")
            
            data = json.loads(request.body) if request.body else {}
            key_id = data.get('key_id')
            user_cert = data.get('user_cert')
            
            log.info(f"[{request_id}] 解析参数 - key_id: {key_id}")

            # 参数验证
            if not key_id:
                log.warning(f"[{request_id}] 参数验证失败: key_id参数不能为空")
                return ErrorResponse(data="key_id参数不能为空")
            if not user_cert:
                log.warning(f"[{request_id}] 参数验证失败: user_cert参数不能为空")
                return ErrorResponse(data="user_cert参数不能为空")

            log.info(f"[{request_id}] 参数验证通过，开始查询密钥信息")

            # 查询密钥
            derive_key_obj = DeriveKey.objects.filter(
                key_id=key_id,
                is_delete=False
            ).first()

            if not derive_key_obj:
                log.warning(f"[{request_id}] 密钥不存在 - key_id: {key_id}")
                return ErrorResponse(data="密钥不存在")
            
            # 用户公钥加密
            # current_date = datetime.now().strftime("%Y%m%d")
            derive_key = derive_key_obj.key
            if env == 'dev':
                derive_key_scerte = self.add_secrets(user_cert, derive_key) 
                derive_key_scerte = base64.b64encode(derive_key_scerte).decode("ascii")
            else:
                status, derive_key_scerte = command_encrypt(user_cert, derive_key)  # 执行加密命令
                if status != 0:
                    return ErrorResponse(code=status, data=None, msg=f"派生密钥加密失败: {derive_key_scerte}")

            result = {
                "key": derive_key_scerte,
                "name": derive_key_obj.description,
                "algorithm": derive_key_obj.algorithm,
                "purpose": derive_key_obj.purpose,
                "status": derive_key_obj.status,
                "created_at": derive_key_obj.created_at.strftime("%Y%m%d%H%M%S%f")[:-3],
                "expires_at": derive_key_obj.expires_at.strftime("%Y%m%d%H%M%S%f")[:-3] if derive_key_obj.expires_at else None,
                "version": derive_key_obj.version,
                "derive_id": derive_key_obj.derive_id
            }

            log.info(f"[{request_id}] 密钥查询成功 - key_id: {key_id}, algorithm: {derive_key_obj.algorithm}")

            return DetailResponse(data=result, msg="密钥查询成功")

        except json.JSONDecodeError as e:
            log.error(f"[{request_id}] JSON解析失败: {str(e)}, 请求体: {request_body}")
            return ErrorResponse(data="请求体格式错误，请使用JSON格式")
        except Exception as e:
            log.error(f"[{request_id}] 查询密钥失败: {str(e)}")
            log.error(f"[{request_id}] 异常堆栈: {traceback.format_exc()}")
            return ErrorResponse(data=f"查询密钥失败: {str(e)}")




class DeriveKeyStatusViews(APIView):
    """派生密钥状态管理API"""

    def post(self, request: Request):
        """
        禁用/启用密钥
        POST /keys/{key_id}/disable 或 /keys/{key_id}/enable
        头信息: {
            "APP-ID": "your_app_id",
            "TOKEN": "your_signature_token"
        }
        参数: {
            "senderNonce": "sender_nonce_value",
            "recipNonce": "recip_nonce_value", 
            "messageTime": "20250101000000000"
        }
        """
        client_ip = get_client_ip(request)
        request_id = f"req_{datetime.now().strftime('%Y%m%d%H%M%S%f')[:-3]}"
        
        log.info(f"[{request_id}] 开始处理密钥状态操作请求 - IP: {client_ip}, 路径: {request.path}")
        log.info(f"[{request_id}] 请求头信息: {dict(request.headers)}")
        headers = dict(request.headers)
        body = json.loads(request.body)
        
        # 签名校验
        is_valid, error_msg = validate_signature(headers, body)

        if not is_valid:
            log.warning(f"[{request_id}] 签名校验失败: {error_msg}")
            return ErrorResponse(data=f"签名校验失败: {error_msg}")
        
        log.info(f"[{request_id}] 签名校验通过，开始处理业务逻辑")
        
        # 根据URL路径判断操作类型
        current_path = request.path
        if 'disable' in current_path:
            return self._disable_key(body, request_id, client_ip)
        elif 'enable' in current_path:
            return self._enable_key(body, request_id, client_ip)
        else:
            log.warning(f"[{request_id}] 无效的URL路径: {current_path}")
            return ErrorResponse(data="无效的URL路径")

    def _disable_key(self, body: dict, request_id: str, client_ip: str):
        """
        禁用密钥
        """
        key_id = body.get('key_id')
        log.info(f"[{request_id}] 开始禁用密钥 - key_id: {key_id}")
        
        try:
            # 查询密钥
            derive_key_obj = DeriveKey.objects.filter(
                key_id=key_id,
                is_delete=False
            ).first()

            if not derive_key_obj:
                log.warning(f"[{request_id}] 密钥不存在 - key_id: {key_id}")
                return ErrorResponse(data="密钥不存在")

            # 更新状态
            old_status = derive_key_obj.status
            derive_key_obj.status = 'inactive'
            derive_key_obj.save()

            # 记录审计日志
            DeriveKeyAuditLog.objects.create(
                key_id=key_id,
                operation='disable',
                operator='system',
                ip_address=client_ip,
                user_agent='',
                details=f"禁用密钥 - 旧状态: {old_status}, 新状态: inactive",
                expired_at=datetime.now() + timedelta(days=365)
            )

            result = {
                "key_id": key_id,
                "status": derive_key_obj.status,
                "disabled_at": datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
            }

            log.info(f"[{request_id}] 密钥禁用成功 - key_id: {key_id}, 旧状态: {old_status}, 新状态: inactive")

            return DetailResponse(data=result, msg="密钥禁用成功")

        except Exception as e:
            log.error(f"[{request_id}] 禁用密钥失败: {str(e)}")
            log.error(f"[{request_id}] 异常堆栈: {traceback.format_exc()}")
            return ErrorResponse(data=f"禁用密钥失败: {str(e)}")

    def _enable_key(self, body: dict, request_id: str, client_ip: str):
        """
        启用密钥
        """
        key_id = body.get('key_id')
        log.info(f"[{request_id}] 开始启用密钥 - key_id: {key_id}")
        
        try:
            # 查询密钥
            derive_key_obj = DeriveKey.objects.filter(
                key_id=key_id,
                is_delete=False
            ).first()

            if not derive_key_obj:
                log.warning(f"[{request_id}] 密钥不存在 - key_id: {key_id}")
                return ErrorResponse(data="密钥不存在")

            # 更新状态
            old_status = derive_key_obj.status
            derive_key_obj.status = 'active'
            derive_key_obj.save()

            # 记录审计日志
            DeriveKeyAuditLog.objects.create(
                key_id=key_id,
                operation='enable',
                operator='system',
                ip_address=client_ip,
                user_agent='',
                details=f"启用密钥 - 旧状态: {old_status}, 新状态: active",
                expired_at=datetime.now() + timedelta(days=365)
            )

            result = {
                "key_id": key_id,
                "status": derive_key_obj.status,
                "enabled_at": datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
            }

            log.info(f"[{request_id}] 密钥启用成功 - key_id: {key_id}, 旧状态: {old_status}, 新状态: active")

            return DetailResponse(data=result, msg="密钥启用成功")

        except Exception as e:
            log.error(f"[{request_id}] 启用密钥失败: {str(e)}")
            log.error(f"[{request_id}] 异常堆栈: {traceback.format_exc()}")
            return ErrorResponse(data=f"启用密钥失败: {str(e)}")
